namespace MicroCloud.CodeGenerator.Views.Entities
{
    [MapTo(typeof(CodeForeignInDto))]
    [MapFrom(typeof(CodeForeign))]
    public class ForeignViewModel : Screen
    {
        private readonly IServiceProvider _provider;

        public ForeignViewModel(IServiceProvider provider)
        {
            _provider = provider;
        }

        public Guid Id { get; set; }

        public string SelfNavigation { get; set; }

        public string SelfForeignKey { get; set; }

        public string OtherEntity { get; set; }

        public string OtherNavigation { get; set; }

        public ForeignRelation ForeignRelation { get; set; }

        public DeleteBehavior? DeleteBehavior { get; set; }

        public IObservableCollection<string> OtherNavigations
        {
            get
            {
                string[] props = new string[0];
                if (!string.IsNullOrEmpty(OtherEntity))
                {
                    var name = TypeHelper.ToSingleTypeName(OtherEntity);
                    props = GetCodeProperties(a => a.Entity.Name == name && a.IsNavigation).Select(a => a.Name).ToArray();
                }
                return new BindableCollection<string>(props);
            }
        }

        public bool IsRequired { get; set; } = true;

        public Guid EntityId { get; set; }

        public void SelfNavigationChanged(SelectionChangedEventArgs args)
        {
            if (args.AddedItems.Count == 0 || args.AddedItems[0] is not string navName) return;

            var props = GetNavForeignPropNames().ToList();
            if (string.IsNullOrEmpty(SelfForeignKey))
            {
                SelfForeignKey = props.FirstOrDefault(a => a.IsForeignKey && a.Name.Contains(navName))?.Name;
            }

            if (string.IsNullOrEmpty(OtherEntity))
            {
                OtherEntity = props.FirstOrDefault(a => a.IsNavigation && a.Name == navName)?.RelateEntity;
            }
        }

        public void SelfForeignKeyChanged(SelectionChangedEventArgs args)
        {
            if (args.AddedItems.Count == 0 || args.AddedItems[0] is not string foreignName)
                return;

            var props = GetNavForeignPropNames().ToList();
            if (string.IsNullOrEmpty(SelfNavigation))
            {
                SelfNavigation = props.FirstOrDefault(a => a.IsNavigation && foreignName.Contains(a.Name))?.Name;
            }

            if (string.IsNullOrEmpty(OtherEntity))
            {
                OtherEntity = props.FirstOrDefault(a => a.IsNavigation && a.Name == SelfNavigation)?.RelateEntity;
            }
        }

        public async void Delete()
        {
            if (MessageBox.Show($"是否删除实体外键“{SelfNavigation??SelfForeignKey}”？", "请确认", MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.Cancel)
            {
                return;
            }
            OperationResult result = null;
            await _provider.ExecuteScopedWorkAsync(async provider =>
            {
                IDataContract contract = provider.GetRequiredService<IDataContract>();
                result = await contract.DeleteCodeForeigns(Id);
            });
            Helper.Notify(result);
            if (!result.Succeeded)
            {
                return;
            }

            ForeignListViewModel list = IoC.Get<ForeignListViewModel>();
            list.Init();
        }

        private CodeProperty[] GetNavForeignPropNames()
        {
            Expression<Func<CodeProperty, bool>> exp = a => a.EntityId == EntityId;
            exp = exp.And(a => a.IsNavigation || a.IsForeignKey);
            return GetCodeProperties(exp);
        }

        private CodeProperty[] GetCodeProperties(Expression<Func<CodeProperty, bool>> exp)
        {
            CodeProperty[] properties = new CodeProperty[0];
            _provider.ExecuteScopedWork(provider =>
            {
                IDataContract contract = provider.GetRequiredService<IDataContract>();
                properties = contract.CodeProperties.Where(exp).ToArray();
            });
            return properties;
        }
    }
}
